package com.appjishu.passport.intercepter;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.appjishu.passport.annotation.RestrictAccess;
import com.appjishu.passport.redis.CommonCacheKey;
import com.appjishu.passport.util.WebUtils;

import lombok.RequiredArgsConstructor;

/**
 * 单用户限流切面
 */
/**
 * 单用户限流切面
 */
@Aspect
@Component
@RequiredArgsConstructor
public class RestrictAccessAspect {
    private final RedisTemplate<String,Integer> redisTemplate;
    private static Integer INIT_VALUE = 1;

    @Around("@annotation(com.appjishu.passport.annotation.RestrictAccess)")
    public Object RestrictAccessFrequency(ProceedingJoinPoint point) throws Throwable {
        //获取当前线程的访问对象
        HttpServletRequest request = WebUtils.getHttpServletRequest();
        //获取访问路径
        String requestURI = request.getRequestURI();
        //获取用户token
        String token = request.getHeader(WebUtils.USER_TOKEN);
        //存在redis中的key
        String key = CommonCacheKey.RESTRICT_ACCESS + requestURI + ":" + token;

        MethodSignature sign = (MethodSignature) point.getSignature();
        Method method = sign.getMethod();
        //获取方法上的注解
        RestrictAccess annotation = method.getAnnotation(RestrictAccess.class);
        int accessFrequency = annotation.accessFrequency();
        long ttl = annotation.ttl();

        //从redis中获取用户再限定时间内访问接口的次数
        Integer value = redisTemplate.opsForValue().get(key);
        if (Objects.nonNull(value) && value >= accessFrequency){
            return "您的操作过于频繁，请待会再试";
        }

        if (Objects.isNull(value)){
            //不存在key则设置初始值并且设置过期时间
            redisTemplate.opsForValue().set(key,INIT_VALUE,ttl, TimeUnit.MILLISECONDS);
        }else {
            //存在则将访问次数+1
            redisTemplate.opsForValue().increment(key);
        }

        //执行接口逻辑
        return point.proceed();
    }

}
